package com.tjvib.service;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.TextUtils;

import com.tjvib.bean.BLEDevice;
import com.tjvib.bean.SensorInfo;
import com.tjvib.ble.BLEManager;
import com.tjvib.ble.OnDeviceSearchListener;
import com.tjvib.common.Callback;
import com.tjvib.event.ScanStatusEvent;
import com.tjvib.sensor.LpmsB2Sensor;
import com.tjvib.sensor.ZeroLabSensor;
import com.tjvib.sensor.Sensor;
import com.tjvib.sensor.ZeroLabSensorData;
import com.tjvib.util.LogUtil;
import com.tjvib.util.SharedPreferencesUtil;
import com.tjvib.util.ToastUtil;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

public class ZeroLabSensorService extends SensorService<ZeroLabSensorData> {

    public static BLEManager bleManager = new BLEManager();
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    List<ZeroLabSensor> discoveredSensors = new ArrayList<>();
    public static List<ZeroLabSensor> connectedSensors = new ArrayList<>();

    IntentFilter intentFilter;

    /**
     * 扫描结果回调
     */
    private OnDeviceSearchListener onDeviceSearchListener = new OnDeviceSearchListener() {
        @Override
        public void onDeviceFound(BLEDevice bleDevice) {
            LogUtil.d("DISCOVERY_DEVICE");
            BluetoothDevice device = bleDevice.getBluetoothDevice();
            if (device == null) {
                LogUtil.e("device == null");
                return;
            }
            synchronized (discoveredSensors) {
                if ((device.getName() != null) && (device.getName().length() > 0)) {
                    if (device.getName().contains("ZL")) {
                        for (ListIterator<ZeroLabSensor> it = discoveredSensors.listIterator(); it.hasNext(); ) {
                            if (device.getAddress().equals(it.next().getAddress()))
                                return;
                        }
                        LogUtil.e("deviceName=" + device.getName());
                        ZeroLabSensor zeroLabSensor = new ZeroLabSensor(device.getName(), device.getAddress(),
                                ZeroLabSensorService.this);
                        zeroLabSensor.setDevice(device);
                        discoveredSensors.add(zeroLabSensor);
                        SharedPreferencesUtil.saveZeroLabSensorName(ZeroLabSensorService.this,
                                device.getAddress(), device.getName());

                        ScanStatusEvent scanStatusEvent = new ScanStatusEvent("DISCOVERY_DEVICE");
                        scanStatusEvent.setBleDevice(bleDevice);
                        EventBus.getDefault().post(scanStatusEvent);
                    }
                }
            }

        }

        @Override
        public void onDiscoveryOutTime() {
            LogUtil.d("DISCOVERY_OUT_TIME");
            EventBus.getDefault().post(new ScanStatusEvent("DISCOVERY_OUT_TIME"));
        }
    };


    /**
     * 蓝牙广播接收器
     */
    private final BroadcastReceiver bleBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (TextUtils.equals(action, BluetoothAdapter.ACTION_DISCOVERY_STARTED)) { //开启搜索
                LogUtil.d("ACTION_DISCOVERY_STARTED");
                EventBus.getDefault().post(new ScanStatusEvent(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
            } else if (TextUtils.equals(action, BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {//完成搜素
                LogUtil.d("ACTION_DISCOVERY_FINISHED");
                EventBus.getDefault().post(new ScanStatusEvent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
            } else if(TextUtils.equals(action, BluetoothAdapter.ACTION_STATE_CHANGED)){   //系统蓝牙状态监听
                LogUtil.d("ACTION_STATE_CHANGED");
                EventBus.getDefault().post(new ScanStatusEvent(BluetoothAdapter.ACTION_STATE_CHANGED));
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,0);
                if(state == BluetoothAdapter.STATE_OFF){
                    LogUtil.d("STATE_OFF");
                    EventBus.getDefault().post(new ScanStatusEvent("STATE_OFF"));
                }else if(state == BluetoothAdapter.STATE_ON){
                    LogUtil.d("STATE_ON");
                    EventBus.getDefault().post(new ScanStatusEvent("STATE_ON"));
                }
            }
        }
    };


    @Override
    public void onCreate() {
        super.onCreate();
        if (intentFilter == null) {
            intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //开始扫描
            intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描结束
            intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//手机蓝牙状态监听
            registerReceiver(bleBroadcastReceiver, intentFilter);
        }

        if(!bleManager.initBle(this)) {
            LogUtil.d("该设备不支持低功耗蓝牙");
            ToastUtil.show("该设备不支持低功耗蓝牙");
        }else{
            if(!bleManager.isEnable()){
                //去打开蓝牙
                bleManager.openBluetooth(this,false);
            }
        }
    }


    @Override
    public void onDestroy() {
        unregisterReceiver(bleBroadcastReceiver);
        super.onDestroy();
    }


    public void startBtDiscovery() {
        if(bleManager == null){
            LogUtil.d("searchBtDevice()-->bleManager == null");
            return;
        }

        if (bleManager.isDiscovery()) { //当前正在搜索设备...
            bleManager.stopDiscoveryDevice();
        }

        //开始搜索
        discoveredSensors.clear();
        bleManager.startDiscoveryDevice(onDeviceSearchListener, 1000);
    }


    public void stopBtDiscovery() {
        if (bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }
    }


    public boolean isBtDiscovery() {
        return bluetoothAdapter.isDiscovering();
    }


    @Override
    public void connectSensor() {
    }


    @Override
    public void connectSensor(String address, Callback callback) {
        ZeroLabSensor sensor = null;
        for (ZeroLabSensor s : discoveredSensors) {
            if (s.getAddress().equals(address)) {
                sensor = s;
                break;
            }
        }

        if (sensor == null) {
            callback.onError("该设备未在发现列表中", null);
            return;
        }

        if (sensor.getConnectionStatus() == Sensor.SENSOR_STATUS_CONNECTED) {
            callback.onSuccess("该设备已连接", null);
            return;
        }

        final ZeroLabSensor sensorToConnect = sensor;

        new Thread(() -> {
            if (!sensorToConnect.connect()) {
                EventBus.getDefault().post(new ScanStatusEvent("CONNECT_FAILURE"));
                callback.onFail("连接失败", null);
            } else {
                connectedSensors.add(sensorToConnect);
                SharedPreferencesUtil.saveZeroLabSensorName(ZeroLabSensorService.this,
                        sensorToConnect.getAddress(), sensorToConnect.getDeviceName());
                callback.onSuccess("连接成功", null);
                EventBus.getDefault().post(new ScanStatusEvent("CONNECT_SUCCESS"));
            }
        }).start();
    }

    @Override
    void disconnectSensor() {
    }

    @Override
    public void disconnectSensor(String address, Callback callback) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                s.disconnect();
                connectedSensors.remove(s);
                break;
            }
        }
        callback.onSuccess("断开成功", null);
    }

    @Override
    public void disconnectAllSensor() {
        for (ZeroLabSensor s : connectedSensors) {
            s.disconnect();
        }
        disconnectSensor();
    }

    @Override
    void disconnectAllSensor(Callback callback) {
        for (ZeroLabSensor s : connectedSensors) {
            s.disconnect();
        }
        connectedSensors.clear();
        callback.onSuccess("断开成功", null);
    }

    @Override
    int getSensorConnectionStatus() {
        return 0;
    }

    @Override
    int getSensorConnectionStatus(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.getConnectionStatus();
            }
        }
        return -1;
    }


    @Override
    void setStreamFrequency(int freq) {

    }

    @Override
    public void setStreamFrequency(String address, int freq) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                s.setStreamFrequency(freq);
                break;
            }
        }
    }


    @Override
    int getStreamFrequency() {
        return 0;
    }

    @Override
    public int getStreamFrequency(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.getStreamFrequency();
            }
        }
        return -1;
    }

    @Override
    ZeroLabSensorData getData() {
        return null;
    }

    @Override
    public ZeroLabSensorData getData(String address) {
        if (connectedSensors.size() > 1) {
            if (connectedSensors.get(0).getImuId(address) == 1)
                return connectedSensors.get(1).getData();
            else
                return connectedSensors.get(1).getData2();
        } else {
            for (ZeroLabSensor s : connectedSensors) {
                if (s.getAddress().equals(address)) {
                    return s.getData();
                }
            }
            return null;
        }
    }

    @Override
    public void resetTimestamp() {
        if(!ZeroLabSensor.isRecording())
            for (ZeroLabSensor s : connectedSensors) {
                s.resetTimestamp();
            }
        else
            ToastUtil.show("结束记录后才能重新设置timestamp");
    }

    @Override
    public void resetTimestamp(String address) {
        if(!ZeroLabSensor.isRecording()) {
            for (ZeroLabSensor s : connectedSensors) {
                if (s.getAddress().equals(address)) {
                    s.resetTimestamp();
                    break;
                }
            }
        }else
            ToastUtil.show("结束记录后才能重新设置timestamp");
    }

    @Override
    public void startRecording() {
        ZeroLabSensor.startRecording(this);
    }

    @Override
    public void stopRecording() {
        ZeroLabSensor.stopRecording();
    }

    @Override
    public boolean isRecording() {
        return ZeroLabSensor.isRecording();
    }

    @Override
    public void discardData() {
        ZeroLabSensor.discardData();
    }

    @Override
    public void storeData(String name, Callback callback) {
        ZeroLabSensor.storeData(name, callback);
    }

    public int getConnectedSensorsSize() {
        connectedSensors.clear();
        for (ZeroLabSensor sensor : discoveredSensors) {
            if (sensor.getConnectionStatus() == Sensor.SENSOR_STATUS_CONNECTED) {
                connectedSensors.add(sensor);
            }
        }
        return connectedSensors.size();
    }


    public List<SensorInfo> getZeroLabSensorInfoList() {
        List<SensorInfo> sensorInfoList = new ArrayList<>();
        for (ZeroLabSensor sensor : discoveredSensors) {
            if (sensor.getConnectionStatus() == Sensor.SENSOR_STATUS_CONNECTED) {
                SensorInfo info = new SensorInfo(sensor.getDeviceName(), sensor.getAddress(), "connected");
                sensorInfoList.add(info);
            }
            if (sensor.getConnectionStatus() == Sensor.SENSOR_STATUS_CONNECTING) {
                SensorInfo info = new SensorInfo(sensor.getDeviceName(), sensor.getAddress(), "connecting");
                sensorInfoList.add(info);
            }
            if (sensor.getConnectionStatus() == Sensor.SENSOR_STATUS_DISCONNECTED) {
                SensorInfo info = new SensorInfo(sensor.getDeviceName(), sensor.getAddress(), "disconnected");
                sensorInfoList.add(info);
            }
        }
        return sensorInfoList;
    }


    public List<SensorInfo> getConnectedZeroLabSensorInfoList() {
        List<SensorInfo> result = new ArrayList<>();
        for (ZeroLabSensor sensor : connectedSensors) {
            SensorInfo info = new SensorInfo(sensor.getDeviceName(), sensor.getAddress(), "connected");
            result.add(info);
        }
        return result;
    }


    public int getImuId(String address) {
//        for (ZeroLabSensor s : connectedSensors) {
////            LogUtil.i("setImageLayoutData s.getAddress()="+s.getAddress()+" size="+connectedSensors.size());
//            if (s.getAddress().equals(address)) {
//                return s.getImuId();
//            }
//        }
        return connectedSensors.get(0).getImuId(address);
    }


    public void setImuId(String address, int value) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                s.setImuId(value);
                break;
            }
        }
    }
    public int getGyroRange(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.getGyroRange();
            }
        }
        return -1;
    }


    public int getAccRange(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.getAccRange();
            }
        }
        return -1;
    }


    public int getMagRange(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.getMagRange();
            }
        }
        return -1;
    }


    public boolean isAccDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isAccDataEnabled();
            }
        }
        return false;
    }

    public boolean isGyroDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isGyroDataEnabled();
            }
        }
        return false;
    }

    public boolean isMagDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isMagDataEnabled();
            }
        }
        return false;
    }

    public boolean isAngularVelDataEnable(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isAngularVelDataEnable();
            }
        }
        return false;
    }

    public boolean isQuaternionDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isQuaternionDataEnabled();
            }
        }
        return false;
    }

    public boolean isEulerDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isEulerDataEnabled();
            }
        }
        return false;
    }

    public boolean isLinAccDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isLinAccDataEnabled();
            }
        }
        return false;
    }

    public boolean isPressureDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isPressureDataEnabled();
            }
        }
        return false;
    }

    public boolean isAltitudeDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isAltitudeDataEnabled();
            }
        }
        return false;
    }

    public boolean isTemperatureDataEnabled(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.isTemperatureDataEnabled();
            }
        }
        return false;
    }

    public int getFilterMode(String address) {
        for (ZeroLabSensor s : connectedSensors) {
            if (s.getAddress().equals(address)) {
                return s.getFilterMode();
            }
        }
        return -1;
    }
}
